package com.ctshk.rpc.finance.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.SysApprovalType;
import com.ctshk.common.enums.SystemBusinessType;
import com.ctshk.common.enums.SystemError;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.common.utils.SnowflakeIdWorker;
import com.ctshk.rpc.finance.dto.onaccount.*;
import com.ctshk.rpc.finance.entity.*;
import com.ctshk.rpc.finance.json.FileJson;
import com.ctshk.rpc.finance.json.OffAccountAmountJson;
import com.ctshk.rpc.finance.mapper.*;
import com.ctshk.rpc.finance.req.bill.RollBackReq;
import com.ctshk.rpc.finance.req.onaccount.*;
import com.ctshk.rpc.finance.service.IFinanceOnAccountService;
import com.ctshk.rpc.system.dto.UserDTO;
import com.ctshk.rpc.system.service.ISysUserService;
import com.ctshk.rpc.workflow.dto.ApprovalCheckDTO;
import com.ctshk.rpc.workflow.dto.ApprovalStartDTO;
import com.ctshk.rpc.workflow.service.ISysApprovalService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;


import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * 财务挂账信息 服务实现类
 * </p>
 *
 * @author 叶冠峰
 * @since 2021-03-30
 */
@DubboService
public class FinanceOnAccountServiceImpl extends ServiceImpl<FinanceOnAccountMapper, FinanceOnAccount> implements IFinanceOnAccountService {

    @Autowired
    private FinanceOnAccountMapper onAccountMapper;
    @Autowired
    private FinanceOnAccountCurrencyQuotaMapper onAccountCurrencyQuotaMapper;
    @Autowired
    private FinanceOnAccountApplyMapper onAccountApplyMapper;
    @Autowired
    private FinanceOnAccountUsageRecordMapper onAccountUsageRecordMapper;
    @Autowired
    private FinanceOffAccountApplyMapper offAccountApplyMapper;

    /*@Autowired
    private RedisTemplate<String, Object> redisTemplate;*/

    @DubboReference
    private ISysApprovalService sysApprovalService;

    @DubboReference
    private ISysUserService sysUserService;



    /**
     * 列表
     *
     * @param req
     * @return
     */
    @Override
    public Result<PageResponse<OnAccountListDTO>> list(OnAccountListReq req) {
        Page<FinanceOnAccount> iPage = new Page<>(req.getPageNo(), req.getPageSize());
        QueryWrapper<FinanceOnAccount> queryWrapper = new QueryWrapper<>();
        //账户类型 1 大客户/代理商挂账,2 内部中心挂账,3 集团公司挂账
        if (Objects.equals(req.getAccountType(),1)){
            queryWrapper.eq(req.getAccountId() != null,"account_id",req.getAccountId());
            queryWrapper.like(StringUtils.isNotBlank(req.getContactName()),"contact_name",req.getContactName());
        }else if (Objects.equals(req.getAccountType(),2)){
            queryWrapper.eq(req.getDeptId() != null,"dept_id",req.getDeptId());
            queryWrapper.like(StringUtils.isNotBlank(req.getContactName()),"contact_name",req.getContactName());
        }
        queryWrapper.eq("account_type",req.getAccountType());
        queryWrapper.eq("is_deleted",0);
        queryWrapper.orderByDesc("gmt_create");
        Page<FinanceOnAccount> page = onAccountMapper.selectPage(iPage, queryWrapper);
        if (CollectionUtils.isEmpty(page.getRecords())) {
            return Result.success(PageResponse.empty(page.getCurrent()));
        }
        List<OnAccountListDTO> list = new ArrayList<>();
        page.getRecords().forEach(item -> {
            OnAccountListDTO dto = EntityUtil.copy(item,OnAccountListDTO.class);
            //获取挂账币种统计
            List<CurrencyQuotaDTO> currencyQuotaList = onAccountCurrencyQuotaMapper.queryListByCurrency(item.getId());
            dto.setCurrencyQuotaList(currencyQuotaList);
            list.add(dto);
        });
        PageResponse<OnAccountListDTO> result = new PageResponse<>(
                list,
                page.getCurrent() == 1,
                page.getTotal() <= (page.getCurrent() * page.getSize()),
                page.getTotal(),
                page.getCurrent(),
                page.getSize());
        return Result.success(result);
    }

    /**
     * 申请挂账
     *
     * @param req
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result add(OnAccountAddReq req) {
        //审批类型
    //    Integer approvalTypeId = ApprovalType.FINANCE_APPLY_OPEN_ACCOUNT_AGENT.getCode();
        Integer approvalTypeId = SysApprovalType.CLIENT_ONACC_FINANCE.getCode();
        //账户类型1 大客户/代理商挂账,2 内部中心挂账,3 集团公司挂账
        if (Objects.equals(req.getAccountType(),1)){
            if (req.getAccountId() == null){
                throw new BusinessException(SystemError.SYS_402);
            }
        }else if (Objects.equals(req.getAccountType(),2)){
            if (req.getDeptId() == null){
                throw new BusinessException(SystemError.SYS_402);
            }
            approvalTypeId = SysApprovalType.IN_ONACC_FINANCE.getCode();
        }
        FinanceOnAccount account = null;
        LocalDateTime now = LocalDateTime.now();
        if (req.getOnAccountId() == null){
            QueryWrapper<FinanceOnAccount> queryWrapper = new QueryWrapper();
            queryWrapper.eq(Objects.equals(req.getAccountType(),1),"account_id",req.getAccountId());
            queryWrapper.eq(Objects.equals(req.getAccountType(),2),"dept_id",req.getDeptId());
            queryWrapper.eq("is_deleted",0);
            account = onAccountMapper.selectOne(queryWrapper);
            if (account == null){
                //新增挂账信息
                account = EntityUtil.copy(req,FinanceOnAccount.class);
                account.setId(SnowflakeIdWorker.nextId());
                account.setEffectiveTime(req.getExpireDate());
                account.setCreateId(req.getUserId());
                account.setGmtCreate(now);
                account.setIsDeleted(0);
                boolean save = save(account);
                if (!save){
                    throw new BusinessException(SystemError.SYS_408);
                }
            }
        }else{
            account = getById(req.getOnAccountId());
            /*account.setEffectiveTime(req.getExpireDate());
            account.setModifiedId(req.getUserId());
            int update = onAccountMapper.updateById(account);
            if (update <= 0){
                throw new BusinessException(SystemError.SYS_408);
            }*/
        }
        //新增申请记录
        FinanceOnAccountApply apply = EntityUtil.copy(req,FinanceOnAccountApply.class);
        apply.setId(SnowflakeIdWorker.nextId());
        apply.setOnAccountId(account.getId());
        apply.setBusinessType(JSON.toJSONString(req.getBusinessType()));
        List<FileJson> filesJson = req.getFilesJson();
        String fileJsonStr = JSON.toJSONString(filesJson);
        apply.setFilesJson(fileJsonStr);
        apply.setApprovalStatus(2);
        apply.setCreateId(req.getUserId());
        apply.setGmtCreate(now);
        apply.setIsDeleted(0);
        int insert = onAccountApplyMapper.insert(apply);
        if (insert <= 0){
            throw new BusinessException(SystemError.SYS_437);
        }
        //发起审批
        Long approvalId = startApproval(apply.getId(), account.getId(), req.getUserId(), approvalTypeId);
        apply.setApprovalId(approvalId);
        int update = onAccountApplyMapper.updateById(apply);
        if (update <= 0){
            throw new BusinessException(SystemError.SYS_437);
        }
        return Result.success(apply.getId());
    }

    /**
     * 挂账详情
     *
     * @param req
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<OnAccountDetailDTO> detail(OnAccountDetailReq req) {
        //挂账信息
        FinanceOnAccount account = getById(req.getId());
        if (account == null || Objects.equals(account.getIsDeleted(),1)){
            throw new BusinessException(SystemError.FINANCE_BILL_17013);
        }
        OnAccountDetailDTO dto = EntityUtil.copy(account,OnAccountDetailDTO.class);
        if (StringUtils.isNotBlank(account.getBusinessTypeList())){
            List<Integer> businessType = JSON.parseArray(account.getBusinessTypeList(), Integer.class);
            dto.setBusinessType(businessType);
        }
        //汇总统计
        QueryWrapper<FinanceOnAccountCurrencyQuota> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("on_account_id",req.getId());
        queryWrapper.eq("is_deleted",0);
        List<FinanceOnAccountCurrencyQuota> quotaList = onAccountCurrencyQuotaMapper.selectList(queryWrapper);
        if (quotaList != null && quotaList.size() > 0){
            List<OnAccountCurrencyQuotaDTO> quotaDTOList = new ArrayList<>();
            quotaList.forEach(quota -> {
                OnAccountCurrencyQuotaDTO quotaDTO = EntityUtil.copy(quota,OnAccountCurrencyQuotaDTO.class);
                quotaDTO.setRemainAmount(quota.getTotalAmount().subtract(quota.getUsedAmount()));
                quotaDTOList.add(quotaDTO);
            });
            dto.setQuotaDTOList(quotaDTOList);
        }
        //申请记录
        if (!Objects.equals(account.getAccountType(),3)){
            QueryWrapper<FinanceOnAccountApply> queryWrapper1 = new QueryWrapper<>();
            queryWrapper1.eq("on_account_id",account.getId());
            queryWrapper1.eq("is_deleted",0);
            queryWrapper1.orderByDesc("gmt_create");
            List<FinanceOnAccountApply> applyList = onAccountApplyMapper.selectList(queryWrapper1);
            if (applyList != null && applyList.size() > 0){
                List<OnAccountApplyDTO> applyDTOList = new ArrayList<>();
                applyList.forEach(apply -> {
                    if (apply.getExpireDate().isBefore(LocalDateTime.now())){
                        //已过期
                        apply.setApprovalStatus(5);
                        apply.setModifiedId(req.getUserId());
                        int update = onAccountApplyMapper.updateById(apply);
                        if (update <= 0){
                            throw new BusinessException(SystemError.SYS_437);
                        }
                    }
                    OnAccountApplyDTO applyDTO = EntityUtil.copy(apply,OnAccountApplyDTO.class);
                    List<Integer> businessType = JSON.parseArray(apply.getBusinessType(), Integer.class);
                    applyDTO.setBusinessType(businessType);
                    //申请人
                    UserDTO userDto = sysUserService.queryCacheUser(apply.getCreateId());
                    if (userDto != null){
                        applyDTO.setApplyUserName(userDto.getFullName());
                        applyDTO.setApplyUserDept(userDto.getDept());
                    }
                    applyDTOList.add(applyDTO);
                });
                dto.setApplyDTOList(applyDTOList);
            }
        }
        //使用记录
        QueryWrapper<FinanceOnAccountUsageRecord> queryWrapper2 = new QueryWrapper<>();
        queryWrapper2.eq("on_account_id",account.getId());
        queryWrapper2.eq("is_deleted",0);
        queryWrapper2.orderByDesc("gmt_create");
        List<FinanceOnAccountUsageRecord> usageRecordList = onAccountUsageRecordMapper.selectList(queryWrapper2);
        if (usageRecordList != null && usageRecordList.size() > 0){
            List<OnAccountUsageRecordDTO> usageRecordDTOList = new ArrayList<>();
            usageRecordList.forEach(usageRecord -> {
                OnAccountUsageRecordDTO usageRecordDTO = EntityUtil.copy(usageRecord, OnAccountUsageRecordDTO.class);
                //销售
                UserDTO userDto = sysUserService.queryCacheUser(usageRecord.getSaleUserId());
                if (userDto != null){
                    usageRecordDTO.setSaleUserName(userDto.getFullName());
                    usageRecordDTO.setSaleUserDept(userDto.getDept());
                }
                usageRecordDTOList.add(usageRecordDTO);
            });
            dto.setUsageRecordDTOList(usageRecordDTOList);
        }
        //销账记录
        QueryWrapper<FinanceOffAccountApply> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("on_account_id",account.getId());
        queryWrapper1.eq("is_deleted",0);
        queryWrapper1.orderByDesc("gmt_create");
        List<FinanceOffAccountApply> offAccountApplyList = offAccountApplyMapper.selectList(queryWrapper1);
        if (offAccountApplyList != null && offAccountApplyList.size() > 0){
            List<OffAccountApplyInfoDTO> offAccountApplyDTOList = new ArrayList<>();
            offAccountApplyList.forEach(offAccountApply -> {
                OffAccountApplyInfoDTO infoDTO = EntityUtil.copy(offAccountApply,OffAccountApplyInfoDTO.class);
                if (StringUtils.isNotBlank(offAccountApply.getCollectionFilesJson())){
                    //收款凭证JSON
                    List<FileJson> fileJsons = JSON.parseArray(offAccountApply.getCollectionFilesJson(), FileJson.class);
                    infoDTO.setCollectionFilesJson(fileJsons);
                }
                if (StringUtils.isNotBlank(offAccountApply.getAmountJson())){
                    //金额JSON
                    List<OffAccountAmountJson> amountJsons = JSON.parseArray(offAccountApply.getAmountJson(), OffAccountAmountJson.class);
                    infoDTO.setAmountJson(amountJsons);
                }
                //申请人
                UserDTO userDto = sysUserService.queryCacheUser(offAccountApply.getCreateId());
                if (userDto != null){
                    infoDTO.setApplyUserName(userDto.getFullName());
                    infoDTO.setApplyUserDept(userDto.getDept());
                }
                offAccountApplyDTOList.add(infoDTO);
            });
            dto.setOffAccountApplyDTOList(offAccountApplyDTOList);
        }
        return Result.success(dto);
    }

    /**
     * 挂账申请详情
     *
     * @param req
     * @return
     */
    @Override
    public Result<OnAccountApplyDetailDTO> applyDetail(OnAccountApplyDetailReq req) {
        if (req.getApplyId() == null && req.getApprovalId() == null){
            throw new BusinessException(SystemError.SYS_402);
        }
        QueryWrapper<FinanceOnAccountApply> queryWrapper = new QueryWrapper<>();
        if (req.getApplyId() != null){
            queryWrapper.eq("id",req.getApplyId());
        }else{
            queryWrapper.eq("approval_id",req.getApprovalId());
        }
        queryWrapper.eq("is_deleted",0);
        FinanceOnAccountApply apply = onAccountApplyMapper.selectOne(queryWrapper);
        if (apply == null){
            throw new BusinessException(SystemError.FINANCE_BILL_17014);
        }
        OnAccountApplyDetailDTO dto = EntityUtil.copy(apply,OnAccountApplyDetailDTO.class);
        dto.setBusinessType(JSON.parseArray(apply.getBusinessType(),Integer.class));
        //附件
        if (StringUtils.isNotBlank(apply.getFilesJson())){
            List<FileJson> fileJsons = JSON.parseArray(apply.getFilesJson(), FileJson.class);
            dto.setFilesJson(fileJsons);
        }
        //申请人
        UserDTO userDto = sysUserService.queryCacheUser(apply.getCreateId());
        if (userDto != null){
            dto.setApplyUserName(userDto.getFullName());
            dto.setApplyUserDept(userDto.getDept());
        }
        FinanceOnAccount account = getById(apply.getOnAccountId());
        if (account == null || Objects.equals(account.getIsDeleted(),1)){
            throw new BusinessException(SystemError.FINANCE_BILL_17013);
        }
        dto.setAccountType(account.getAccountType());
        dto.setAccountName(account.getAccountName());
        dto.setBankAccount(account.getBankAccount());
        dto.setLocation(account.getLocation());
        dto.setContactMobile(account.getContactMobile());
        dto.setContactEmail(account.getContactEmail());
        dto.setContactName(account.getContactName());
        if (!Objects.equals(account.getAccountType(),1)){
            dto.setDeptCode(account.getDeptCode());
            dto.setDeptId(account.getDeptId());
            dto.setDeptName(account.getDeptName());
        }
        return Result.success(dto);
    }

    /**
     * 审批
     *
     * @param req
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result approval(OnAccountApprovalReq req) {
        QueryWrapper<FinanceOnAccountApply> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("approval_id",req.getApprovalId());
        queryWrapper1.eq("is_deleted",0);
        FinanceOnAccountApply apply = onAccountApplyMapper.selectOne(queryWrapper1);
        if (apply == null){
            throw new BusinessException(SystemError.FINANCE_BILL_17014);
        }
        if (!Objects.equals(apply.getApprovalStatus(),2)){
            throw new BusinessException(SystemError.FINANCE_BILL_17012);
        }
        apply.setApprovalStatus(req.getType());
        apply.setModifiedId(req.getUserId());
        int update = onAccountApplyMapper.updateById(apply);
        if (update <= 0){
            throw new BusinessException(SystemError.SYS_437);
        }
        if (Objects.equals(req.getType(),3)){
            //审批通过
            FinanceOnAccount onAccount = onAccountMapper.selectById(apply.getOnAccountId());
            if (onAccount == null || Objects.equals(onAccount.getIsDeleted(),1)){
                throw new BusinessException(SystemError.FINANCE_BILL_17016);
            }
            //更新有效时间
            onAccount.setEffectiveTime(apply.getExpireDate());
            //更新业务类型
            onAccount.setBusinessTypeList(apply.getBusinessType());
            onAccount.setModifiedId(req.getUserId());
            int update1 = onAccountMapper.updateById(onAccount);
            if (update1 <= 0){
                throw new BusinessException(SystemError.SYS_408);
            }
            //更新额度
            QueryWrapper<FinanceOnAccountCurrencyQuota> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("on_account_id",apply.getOnAccountId());
            queryWrapper.eq("currency_id",apply.getCurrencyId());
            queryWrapper.eq("is_deleted",0);
            FinanceOnAccountCurrencyQuota currencyQuota = onAccountCurrencyQuotaMapper.selectOne(queryWrapper);
            if (currencyQuota == null){
                currencyQuota = new FinanceOnAccountCurrencyQuota();
                currencyQuota.setId(SnowflakeIdWorker.nextId());
                currencyQuota.setOnAccountId(apply.getOnAccountId());
                currencyQuota.setCurrencyId(apply.getCurrencyId());
                currencyQuota.setCurrency(apply.getCurrency());
                currencyQuota.setTotalAmount(apply.getApplyAmount());
                currencyQuota.setUsedAmount(BigDecimal.ZERO);
                currencyQuota.setWriteOffAmount(BigDecimal.ZERO);
                currencyQuota.setCurrencyId(apply.getCurrencyId());
                currencyQuota.setCreateId(req.getUserId());
                currencyQuota.setIsDeleted(0);
                int insert = onAccountCurrencyQuotaMapper.insert(currencyQuota);
                if (insert <= 0){
                    throw new BusinessException(SystemError.SYS_437);
                }
            }else{
                currencyQuota.setModifiedId(req.getUserId());
                currencyQuota.setTotalAmount(currencyQuota.getTotalAmount().add(apply.getApplyAmount()));
                int updateById = onAccountCurrencyQuotaMapper.updateById(currencyQuota);
                if (updateById <= 0){
                    throw new BusinessException(SystemError.SYS_437);
                }
            }
        }
        Result<ApprovalCheckDTO> check = sysApprovalService.check(req.getApprovalId(), req.getUserId(), req.getType(), req.getComments());
        if (check == null || !check.getData().getIsFinish()){
            throw new BusinessException(SystemError.SYS_437);
        }
        return Result.success(apply.getId());
    }

    /**
     * 申请销账-选择挂账明细列表
     *
     * @param req
     * @return
     */
    @Override
    public Result<PageResponse<OnAccountDetailListDTO>> detailList(OnAccountDetailListReq req) {
        Page<OnAccountDetailListDTO> iPage = new Page<>(req.getPageNo(), req.getPageSize());
        Page<OnAccountDetailListDTO> page = onAccountUsageRecordMapper.queryListByOnAccount(req,iPage);
        if (CollectionUtils.isEmpty(page.getRecords())) {
            return Result.success(PageResponse.empty(page.getCurrent()));
        }
        page.getRecords().forEach(dto -> {
            UserDTO userDto = sysUserService.queryCacheUser(dto.getSaleUserId());
            if (userDto != null){
                dto.setSaleUserDept(userDto.getDept());
            }
        });
        PageResponse<OnAccountDetailListDTO> result = new PageResponse<>(
                page.getRecords(),
                page.getCurrent() == 1,
                page.getTotal() <= (page.getCurrent() * page.getSize()),
                page.getTotal(),
                page.getCurrent(),
                page.getSize());
        return Result.success(result);
    }

    /**
     * 撤回审批
     *
     * @param req
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result rollBack(RollBackReq req) {
        QueryWrapper<FinanceOnAccountApply> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("approval_id",req.getApprovalId());
        queryWrapper1.eq("is_deleted",0);
        FinanceOnAccountApply apply = onAccountApplyMapper.selectOne(queryWrapper1);
        if (apply == null){
            throw new BusinessException(SystemError.FINANCE_BILL_17014);
        }
        if (!Objects.equals(apply.getCreateId(),req.getUserId())){
            throw new BusinessException(SystemError.FINANCE_ERROR_17039);
        }
        apply.setIsDeleted(1);
        apply.setModifiedId(req.getUserId());
        int del = onAccountApplyMapper.updateById(apply);
        if (del <= 0){
            throw new BusinessException(SystemError.SYS_437);
        }
        Result<ApprovalCheckDTO> check = sysApprovalService.check(req.getApprovalId(), req.getUserId(), 0, null);
        if (check == null || !check.getData().getIsFinish()){
            throw new BusinessException(SystemError.SYS_437);
        }
        return Result.success(req.getApprovalId());
    }


    /**
     * 发起审批流程
     * @param id
     * @param businessId
     * @param userId
     * @param approvalTypeId
     */
    private Long startApproval(Long id, Long businessId, Long userId,Integer approvalTypeId) {
        Map<String, Object> extendParams = new HashMap<>();
        extendParams.put("id", id);
        try{
            Result<ApprovalStartDTO> approvalResult = sysApprovalService.start(SystemBusinessType.FINANCE.getCode(),
                    approvalTypeId, businessId,
                    userId, null, JSON.toJSONString(extendParams));
            if (!approvalResult.isSuccess()) {
                throw new BusinessException(SystemError.CUSTOM_ORDER_4044);
            }
            return approvalResult.getData().getApprovalId();
        }catch (Exception e){
            throw new BusinessException(SystemError.SYS_422);
        }
    }

}
